﻿/**
 * author:  Martin Hrabos
 * year:    2016
 * email:   hrabosmartin@gmail.com
 * 
 * FIT Brno University of Technology / ASCR Brno
 */

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;

namespace CorrCL
{
    /*
     * Class for displaying result signals 
     */
    public partial class SignalPlotter : Form
    {

        private float frequency;
        private ResultPoint resultPoint;
        private string sourceFile;

        // Create object with entered results and frequency
        public SignalPlotter(ResultPoint res, float frequency, long windowSize, long windowOffset, string sourceFile)
        {
            InitializeComponent();
            this.frequency = frequency;
            this.resultPoint = res;
            this.sourceFile = sourceFile;
            float[] values = res.getSignal();

            // Create chart series
            chart1.Series["Max Correlation"].ChartType = SeriesChartType.Line;
            long length = values.Length;
            for (long i = 0; i < length; i++)
            {

                chart1.Series["Max Correlation"].Points.AddXY((i*windowOffset + windowSize / 2) / frequency, values[i]);
            }

            chart1.ChartAreas[0].CursorX.IsUserEnabled = true;
            chart1.ChartAreas[0].CursorX.IsUserSelectionEnabled = true;
            //chart1.ChartAreas[0].CursorX.IntervalType = DateTimeIntervalType.Seconds;
            chart1.ChartAreas[0].CursorX.Interval = 0.05D;

            chart1.ChartAreas[0].AxisX.ScaleView.SmallScrollSize = 0.05D;
            chart1.ChartAreas[0].AxisX.ScaleView.Zoomable = true;
            chart1.ChartAreas[0].AxisX.LabelStyle.Format = "0.00";

            chart1.ChartAreas[0].AxisX.Title = "Block position in time";
            chart1.ChartAreas[0].AxisY.Title = "Coefficient";

            chart1.Titles.Clear();
            chart1.Titles.Add(String.Format("Correlation between channel {0} and {1}", res.label1, res.label2));

            TextAnnotation text = new TextAnnotation();
            text.Text = sourceFile;
            text.X = 0;
            text.Y = 3;
            chart1.Annotations.Add(text);


            chart1.Invalidate();

            label4.Text = String.Format("{0:0.000}", res.getMinValue());
            label4.ForeColor = ResultPoint.calculateColor(res.getMinValue());
            label5.Text = String.Format("{0:0.000}", res.getMedianValue());
            label5.ForeColor = ResultPoint.calculateColor(res.getMedianValue());
            label6.Text = String.Format("{0:0.000}", res.getMaxValue());
            label6.ForeColor = ResultPoint.calculateColor(res.getMaxValue());

            label9.Text = (res.getMinValueIndex()+1).ToString();
            label10.Text = (res.getMaxValueIndex()+1).ToString();

            listBox1.DrawMode = DrawMode.OwnerDrawVariable;

            long startIndex = 0;
            long endIndex = 0;
            long index = 1;
            foreach (float[] block in res.getBlocks())
            {
                endIndex = startIndex + windowSize;
                if (endIndex > res.originSize)
                    endIndex = res.originSize;
                listBox1.Items.Add(new ListBoxItem(String.Format(("{0:0.00} - {1:0.00}"), startIndex / frequency, endIndex / frequency), ResultPoint.calculateColor(block.Max()), block, index));
                startIndex += windowOffset;
                index++;
            }
            listBox1.DrawItem += new DrawItemEventHandler(listBox1_DrawItem);

            this.ActiveControl = listBox1;
            listBox1.Focus();
            if (listBox1.Items.Count > 0)
            {
                listBox1.SelectedItem = listBox1.Items[0];
            }

        }

        private class ListBoxItem
        {
            public string value;
            private Color color;
            private float[] data;
            public long blockIndex;

            public ListBoxItem(string value, Color color, float[] data, long index)
            {
                this.value = value;
                this.color = color;
                this.data = data;
                this.blockIndex = index;
            }

            public override string ToString()
            {
                return String.Format("{0}. {1}", this.blockIndex, this.value);
            }

            public Color getColor()
            {
                return this.color;
            }

            public float[] getData()
            {
                return this.data;
            }
        }

        private void listBox1_DrawItem(object sender, DrawItemEventArgs e)
        {
            // Draw the background of the ListBox control for each item.
            e.DrawBackground();
            // Define the default color of the brush as black.
            Brush myBrush = Brushes.Black;
  


            ListBoxItem item = (ListBoxItem)listBox1.Items[e.Index];

            e.Graphics.DrawString(item.ToString(),
                e.Font, Brushes.Black, e.Bounds.X+12, e.Bounds.Y, StringFormat.GenericDefault);
            e.Graphics.FillRectangle(new SolidBrush(item.getColor()), e.Bounds.X, e.Bounds.Y+2, 10, 10);
            // If the ListBox has focus, draw a focus rectangle around the selected item.
            e.DrawFocusRectangle();
        }

        // Function for copying chart to clipboard
        private void button1_Click(object sender, EventArgs e)
        {
            using (MemoryStream ms = new MemoryStream())
            {
                chart1.SaveImage(ms, ChartImageFormat.Bmp);
                Bitmap bm = new Bitmap(ms);
                Clipboard.SetImage(bm);
            }
        }

        private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            chart2.Series["Correlation"].Points.Clear();
            chart2.Titles.Clear();
            
            Debug.WriteLine(listBox1.SelectedItem.ToString());
            ListBoxItem item = (ListBoxItem)listBox1.SelectedItem;
            float[] values = item.getData();
            // Create chart series
            chart2.Series["Correlation"].ChartType = SeriesChartType.Line;
            long length = values.Length;
            for (long i = 0; i < length; i++)
            {
                chart2.Series["Correlation"].Points.AddXY((i - length / 2) / frequency, values[i]);
            }

            chart2.ChartAreas[0].CursorX.IsUserEnabled = true;
            chart2.ChartAreas[0].CursorX.IsUserSelectionEnabled = true;
            //chart1.ChartAreas[0].CursorX.IntervalType = DateTimeIntervalType.Seconds;
            chart2.ChartAreas[0].CursorX.Interval = 0.05D;

            chart2.ChartAreas[0].AxisX.ScaleView.SmallScrollSize = 0.05D;
            chart2.ChartAreas[0].AxisX.ScaleView.Zoomable = true;
            chart2.ChartAreas[0].AxisX.LabelStyle.Format = "0.00";

            chart2.ChartAreas[0].AxisX.Title = "Time [sec.]";
            chart2.ChartAreas[0].AxisY.Title = "Coefficient";

            chart2.Titles.Add(String.Format("Block no. {0} in time {1:0.00} sec.", item.blockIndex, item.value));

            TextAnnotation text = new TextAnnotation();
            text.Text = sourceFile;
            text.X = 0;
            text.Y = 3;
            chart2.Annotations.Add(text);

            chart2.Invalidate();

            float min = values.Min();
            float max = values.Max();
            float medianValue;

            // Calculate median
            float[] tmpArr = new float[values.Length];


            // Create deep copy of an array
            for (int i = 0; i < tmpArr.Length; i++)
            {
                tmpArr[i] = values[i];
            }
            Array.Sort(tmpArr);
            int mid = tmpArr.Length / 2;
            if (tmpArr.Length % 2 == 0)
            {
                medianValue = (tmpArr[mid - 1] + tmpArr[mid]) / 2;
            }
            else
            {
                medianValue = tmpArr[mid / 2];
            }

            label12.Text = String.Format("{0:0.000}", min);
            label12.ForeColor = ResultPoint.calculateColor(min);
            label14.Text = ((Array.IndexOf(values, min) - length / 2) / frequency).ToString();

            label16.Text = String.Format("{0:0.000}", medianValue);

            label18.Text = String.Format("{0:0.000}", max);
            label18.ForeColor = ResultPoint.calculateColor(max);
            label20.Text = ((Array.IndexOf(values, max) - length / 2) / frequency).ToString();

        }

        // Export to CSV
        private void button2_Click(object sender, EventArgs e)
        {
            SaveFileDialog dialog = new SaveFileDialog();
            dialog.Filter = "CSV files (*.csv) | *.csv";
            dialog.FilterIndex = 0;
            dialog.RestoreDirectory = true;

            if (dialog.ShowDialog() == DialogResult.OK)
            {

                SignalFileWriter h = new SignalFileWriter(dialog.FileName);
                h.WriteCSV(resultPoint, frequency);

            }
        }
    }
}
